home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / admin / chfssize < prev    next >
Encoding:
Korn shell script  |  1997-08-26  |  7.8 KB  |  237 lines

  1. #!/bin/ksh
  2. # @(#) chfssize.ksh 1.3 95/10/14
  3. # Note: this program requires the extra utilities 'asc' and 'chr';
  4. # asc requires gawk 2.15.5 or later.  They should be available here:
  5. # ftp://ftp.armory.com/pub/scripts/asc
  6. # ftp://ftp.armory.com/pub/scripts/chr
  7. # ftp://ftp.armory.com/pub/scobins/gawk (SCO binary)
  8. # 94/10/15 john h. dubois iii (john@armory.com)
  9. # 95/08/02 Added 0 option for oldsize, and p option.
  10. # 95/08/30 Added reporting of division size, and 0 option for newsize
  11. # 95/10/14 Run fsck -y -ofull for HTFS filesystems.
  12.  
  13. lngname=${0##*/}
  14. Usage="Usage: $lngname [-hrpf] <device-name> [<oldsize> <newsize>]"
  15. NoReduce=true
  16. Run_fsck=false
  17. debug=false
  18. PrintCommand=false
  19.  
  20. while getopts :hrpfx opt; do
  21.     case $opt in
  22.     h)
  23.     echo \
  24. "$lngname: change AFS or EAFS filesystem size.
  25. $lngname increases the size of a filesystem by increasing the value of the
  26. fsize field in the filesystem superblock.  This should only be done after
  27. modifying the divvy table to allocate extra space to a filesystem by increasing
  28. the value of the 'Last Block'.  This is only possible if there is space
  29. available on the partition after the filesystem.  The size of a filesystem
  30. should only be increased, not decreased, because there is no facility for
  31. ensuring that no blocks are used at the end of the filesystem.
  32. $Usage
  33. <device-name> is the device the filesystem resides on.  The name of the block
  34. device should be given, e.g. /dev/u.  If only <device-name> is given, the
  35. current filesystem size is printed.  <oldsize> and <newsize> are the current
  36. and desired sizes of the filesystem, in 1K blocks.  <oldsize> must be given as
  37. a check that the right device and units are being used.  If 0 is given for
  38. <oldsize>, no check is done.  This avoids the need for the \"asc\" utility, but
  39. is more dangerous.  If 0 is given for <newsize>, the current division size is
  40. used.
  41. This utility only patches the fsize field.  It does not do anything to add
  42. the newly included blocks to the filesystem.  To do that, you must run
  43. fsck -s <block-device-name>
  44. after this program completes succesfully.  NOTE that patching the superblock is
  45. intrinsically dangerous and should only be done after a level-0 backup of a
  46. filesystem.  This utility has been tested on EAFS filesystems, and minimally
  47. tested on HTFS filesystems.  It should also work on AFS filesystems.  It should
  48. never be used on a mounted filesystem.  To change the size of the root
  49. filesystem, boot from a boot/root set or another division, or boot with the
  50. root filesystem mounted read-only (use the ronly boot parameter).  The -p
  51. option can be used to generate a command to issue when booting from a
  52. boot/root set.
  53. Example:
  54. $lngname /dev/u 1000000 1116000
  55. Options:
  56. -h: Print this help.
  57. -p: Instead of changing the filesystem size, show a simple echo-to-dd command
  58.     that would change the filesystem size.  This can be used to generate a
  59.     command that can be used on another system or e.g. when booting in a manner
  60.     that does not allow this utility to be used directly.  Use of this option
  61.     changes all error checks to warnings.
  62. -f: Run 'fsck -s' (for EAFS) or 'fsck -y -ofull' (for HTFS) on the device after
  63.     changing its size.
  64. -r: Reduce the size of a filesystem.  Without this option, $lngname will refuse
  65.     to let the size be made smaller than it currently is.  This option might
  66.     be used if a filesystem was expanded and then needed to be restored to its
  67.     original size without it ever having been mounted.  It should NOT be used
  68.     on an HTFS filesystem except specifically to restore the size of a
  69.     filesystem that was increased in size with this utility."
  70.     exit 0
  71.     ;;
  72.     x)
  73.     debug=true
  74.     ;;
  75.     f)
  76.     Run_fsck=true
  77.     ;;
  78.     r)
  79.     NoReduce=false
  80.     ;;
  81.     p)
  82.     PrintCommand=true
  83.     ;;
  84.     +?)
  85.     print -u2 "$lngname: options should not be preceded by a '+'."
  86.     exit 1
  87.     ;;
  88.     :)
  89.         print -r -u2 -- \
  90.         "$lngname: Option '$OPTARG' requires a value.  Use -h for help."
  91.         exit 1
  92.         ;;
  93.     ?)
  94.     print -u2 "$lngname: $OPTARG: bad option.  Use -h for help."
  95.     exit 1
  96.     ;;
  97.     esac
  98. done
  99.  
  100. $debug && set -x
  101.  
  102. # remove args that were options
  103. let OPTIND=OPTIND-1
  104. shift $OPTIND
  105.  
  106. if [ $# -eq 0 -o $# -eq 2 -o $# -gt 3 ]; then
  107.     print -u2 "$Usage\nUse -h for help."
  108.     exit
  109. fi
  110.  
  111. # Usage: GetMajMin device-name ...
  112. # Prints the major #, minor #, and name of each device, one set per line.
  113. # or nothing if the path is not a device.  Output lines are not neccessarily in
  114. # the same order as the parameters.
  115. # Returns 1 if no names were devices, else 0.
  116. function GetMajMin {
  117. # l -gon output looks like this:
  118. #     1        2   3   4  5
  119. # br--r-----   1   1, 40 Aug 10 18:26 /dev/root
  120.     typeset IFS=" ," maj min
  121.     typeset -i exitVal=1
  122.  
  123.     l -gon -- "$@" | while read line; do
  124.     set -- $line
  125.     [[ $# -lt 8 || "$3" != +([0-9]) || "$4" != +([0-9]) ]] && continue
  126.     maj=$3
  127.     min=$4
  128.     shift 7
  129.     print -r "$maj $min $*"
  130.     exitVal=0
  131.     done
  132.     return $exitVal
  133. }
  134.  
  135. # Usage: DivInfo device-name
  136. # Prints starting block, ending block, size, major #, minor #, div #, name
  137. # Returns 0 on success, 1 if the given file was not a device, 2 if it is not
  138. # on a UNIX partition, 3 if it is the whole partition (not a division),
  139. # 4 if it is not a divvied device.
  140. function DivInfo {
  141.     typeset -i Division maj min divnum start end Part
  142.     typeset name Device=$1
  143.  
  144.     GetMajMin "$Device" | read maj min name || return 1
  145.     Division=min%8
  146.     Part=min/8%8
  147.     [ Part -lt 1 -o Part -gt 5 ] && return 2
  148.     [ Division -eq 7 ] && return 3
  149.  
  150.     # This assumes we can run divvy on a division and have it operate on the
  151.     # partition that the division is in.
  152.     /etc/divvy -P $Division | read divnum start end || return 4
  153.     print -r "$start $end $((end-start+1)) $maj $min $Division $Device"
  154.     return 0
  155. }
  156.  
  157. function Error {
  158.     if $PrintCommand; then
  159.     print -u2 "$lngname: WARNING: $*"
  160.     else
  161.     print -u2 "$lngname: FATAL ERROR: $*"
  162.     exit 1
  163.     fi
  164. }
  165.  
  166. Device=$1
  167.  
  168. [ ! -b "$Device" ] && Error "$Device: not a block device."
  169. DivInfo "$Device" | read st en DivSize other ||
  170. Error "Could not get size of division $Device"
  171.  
  172. $PrintCommand || set -e        # for extra safety
  173.  
  174. # Do this if EITHER we must have the information, or the command exists.
  175. # If we must have the info and the command isn't found, we will exit due to
  176. # -e being set.
  177. if [ "$2" != 0 ] || type asc > /dev/null 2>&1; then
  178.     dd bs=4 iseek=129 count=1 if="$Device" 2>/dev/null | asc -l | read blocks
  179. fi
  180.  
  181. if [ $# -ne 3 ]; then
  182.     print "$lngname: Current size of filesystem on $Device: $blocks blocks."
  183.     print "$lngname: Current size of division $Device: $DivSize blocks."
  184.     exit 0
  185. fi
  186.  
  187. [ -n "$blocks" ] && print "Old filesystem size: $blocks blocks."
  188.  
  189. [ 0 != "$2" -a "$blocks" -ne "$2" ] && Error \
  190. "fs size ($blocks blocks) doesn't match given value ($2 blocks)"
  191.  
  192. typeset -i NewSize
  193. if [ 0 = "$3" ]; then
  194.     NewSize=DivSize
  195.     print "New filesystem size (division size): $NewSize blocks."
  196. else
  197.     NewSize=$3
  198.     [ -n "$DivSize" -a "$DivSize" -ne NewSize ] &&
  199.     print \
  200.     "Note: new filesystem size is not the same as the current division size."
  201. fi
  202.  
  203. if [ NewSize -lt "$2" ] && $NoReduce; then
  204.     Error \
  205. "New fs size ($NewSize blocks) is smaller than old size ($2 blocks).
  206. Use the -r option if you really want to reduce the fs size (dangerous)."
  207. fi
  208.  
  209. if $PrintCommand; then
  210.     # Use -r because chr will emit escape codes
  211.     print -r \
  212. "Issue the following command to change the size of $Device.
  213. WARNING: No sanity checks will be done at the time you issue this command!!!
  214. echo \"$(chr -e -l4 "$NewSize")\" | dd bs=4 count=1 oseek=129 of=$Device"
  215.  
  216. else
  217.     chr -l4 "$NewSize" | dd bs=4 count=1 oseek=129 of="$Device" 2>/dev/null
  218.     if $Run_fsck; then
  219.     fstype=$(/etc/fstyp $Device)
  220.     case "$fstype" in
  221.     EAFS)
  222.         fsckCmd="fsck -s $Device"
  223.         ;;
  224.     HTFS)
  225.         fsckCmd="fsck -y -ofull $Device"
  226.         ;;
  227.     *)
  228.         print -u2 \
  229. "Filesystem type is '$fstype'; only know what arguments
  230. to give fsck for EAFS or HTFS filesystems.  fsck not run."
  231.         exit 1
  232.     esac
  233.     print "Running '$fsckCmd'"
  234.     $fsckCmd
  235.     fi
  236. fi
  237.